#include <QtOpenGL>
#include "camara.h"
#include "vector3d.h"

Camara::Camara()
{
    modo = CAMARA_MODO_PERSPECTIVA;

    anguloVision = 90;
    relacionAnchoAlto = 1;
    profundidadMinima = 0;
    profundidadMaxima = 100;
 
    origenHorizontalOrto = 0;
    origenVerticalOrto = 0;
    anchoOrto = 1;
    altoOrto = 1;

    posicion.setCoordenadas(5, 5, 0);
    puntoMira.setCoordenadas(0, 0, 0);
    vectorArriba.setCoordenadas(0, 0, 1);
}

Camara::~Camara()
{

}

void Camara::aplicar()
{     
    GLint viewport[4]; 
    glGetIntegerv(GL_VIEWPORT, viewport); 
    double anchoViewport = viewport[2];
    double altoViewport = viewport[3];

    double alto, ancho;
    if (modo == CAMARA_MODO_ORTOGONAL2D) {
        
        double x = origenHorizontalOrto;//(anchoOrto - ancho) / 2;
        double y = origenVerticalOrto;//(altoOrto - alto) / 2;
        if (anchoViewport / altoViewport < anchoOrto / altoOrto) {            
            ancho = anchoOrto;
            alto = ancho * altoViewport / anchoViewport;
            y -= (alto - altoOrto) / 2;           
        } else {
            alto = altoOrto;
            ancho = alto * anchoViewport / altoViewport;
            x -= (ancho - anchoOrto) / 2;
        }

        gluOrtho2D(x, x + ancho, y, y + alto);

    } else if (modo == CAMARA_MODO_ORTOGONAL) {
        glOrtho(
            origenHorizontalOrto, origenHorizontalOrto + anchoOrto,
            origenVerticalOrto, origenVerticalOrto + altoOrto,
            profundidadMinima, profundidadMaxima);
    } else {        
        gluPerspective(anguloVision, relacionAnchoAlto, profundidadMinima, profundidadMaxima);
    
        gluLookAt(posicion.getX(), posicion.getY(), posicion.getZ(),
            puntoMira.getX(), puntoMira.getY(), puntoMira.getZ(),
            vectorArriba.getX(), vectorArriba.getY(), vectorArriba.getZ());
    }
    
}

void Camara::acercar(float desplazamiento)
{
    Vector3d vectorDireccion(posicion, puntoMira);
    vectorDireccion.setModulo(desplazamiento);
    vectorDireccion.desplazarPunto(posicion);
}

void Camara::alejar(float desplazamiento)
{
    acercar(desplazamiento);
}

void Camara::desplazar(const Vector3d& vectorDesplazamiento)
{
    vectorDesplazamiento.desplazarPunto(posicion);
    vectorDesplazamiento.desplazarPunto(puntoMira);
}

void Camara::desplazar(double x, double y, double z)
{
    desplazar(Vector3d(x, y, z));
}

void Camara::girarHorizontalmente(const Angulo& angulo)
{
    girar(angulo, 0);
}

void Camara::girarVerticalmente(const Angulo& angulo)
{
    girar(0, angulo);
}

void Camara::girar(const Angulo& anguloHorizontal, const Angulo& anguloVertical)
{
    Vector3d vectorGiro(posicion, puntoMira);
    vectorGiro.girar(anguloHorizontal, anguloVertical);

    puntoMira = posicion;
    vectorGiro.desplazarPunto(puntoMira);
}

void Camara::rotarSobrePuntoVista(const Angulo& anguloHorizontal, const Angulo& anguloVertical)
{
    Vector3d vectorGiro(puntoMira, posicion);
    vectorGiro.girar(anguloHorizontal, anguloVertical);

    posicion = puntoMira;
    vectorGiro.desplazarPunto(posicion);
}
